﻿using System;
using System.Collections.Generic;
using Medianamik.Core.DAL;

namespace Medianamik.Core.Sugar
{
    public static class PagingUtil
    {
        public static PagerCollection GetPagesToDisplay<T>(this PagedCollection<T> collection,
          int numberOfElementsPerPage, int numberOfPagesToDisplay, string queryStringPageName,
          string pageUrl, int currentPageIndex)
        {
            return GetPagesToDisplay(queryStringPageName, pageUrl,
                (int)Math.Ceiling(collection.TotalCount / (double)numberOfElementsPerPage),
                numberOfPagesToDisplay, currentPageIndex);
        }

        public static PagerCollection GetPagesToDisplay(string queryStringPageName,
            string pageUrl, int numberOfPages, int numberOfPagesToDisplay,
            int currentPageIndex)
        {
            if (numberOfPagesToDisplay % 2 != 1)
                throw new ArgumentException("numberOfPagesToDisplay%2 != 1");

            var pageList = new List<PagerPage>();

            var restOfPages = (int)Math.Floor((double)numberOfPagesToDisplay / 2);
            var hasPrefix = currentPageIndex > (restOfPages + 1) && numberOfPages > numberOfPagesToDisplay;
            var hasSuffix = numberOfPages - currentPageIndex > restOfPages && numberOfPages > numberOfPagesToDisplay;

            if (hasPrefix && hasSuffix)
            {
                for (var i = currentPageIndex - restOfPages; i <= currentPageIndex + restOfPages; i++)
                {
                    pageList.Add(new PagerPage(queryStringPageName, i, pageUrl, currentPageIndex));
                }
            }
            else if (hasPrefix)
            {
                var numbers = new List<int>();

                for (var i = numberOfPages; i > numberOfPages - numberOfPagesToDisplay; i--)
                {
                    numbers.Add(i);
                }

                numbers.Reverse();

                for (var i = 0; i < numbers.Count; i++)
                {
                    pageList.Add(new PagerPage(queryStringPageName, numbers[i], pageUrl, currentPageIndex));
                }
            }
            else
            {
                var end = numberOfPages > numberOfPagesToDisplay ? numberOfPagesToDisplay : numberOfPages;
                for (var i = 1; i <= end; i++)
                {
                    pageList.Add(new PagerPage(queryStringPageName, i, pageUrl, currentPageIndex));
                }
            }

            return new PagerCollection(pageList, hasPrefix, hasSuffix);
        }


        public class PagerCollection
        {
            private readonly List<PagerPage> _pages;
            private readonly bool _hasPrefix;
            private readonly bool _hasSuffix;

            public PagerCollection(List<PagerPage> pages, bool hasPrefix, bool hasSuffix)
            {
                _pages = pages;
                _hasPrefix = hasPrefix;
                _hasSuffix = hasSuffix;
            }

            public bool HasSuffix
            {
                get { return _hasSuffix; }
            }

            public bool HasPrefix
            {
                get { return _hasPrefix; }
            }

            public List<PagerPage> Pages
            {
                get { return _pages; }
            }
        }

        public class PagerPage
        {
            private readonly string _queryStringPageName;
            private readonly int _index;
            private readonly string _pageURL;
            private readonly int _currentPageIndex;
            private readonly bool _isCurrentPage;
            private readonly string _url;

            public PagerPage(string queryStringPageName, int index, string pageUrl, int currentPageIndex)
            {
                _queryStringPageName = queryStringPageName;
                _index = index;
                _pageURL = pageUrl;
                _currentPageIndex = currentPageIndex;
                _isCurrentPage = index == currentPageIndex;
                _url = GetValidUrl(pageUrl, queryStringPageName, index);
            }

            public string URL
            {
                get { return _url; }
            }

            public bool IsCurrentPage
            {
                get { return _isCurrentPage; }
            }

            public int CurrentPageIndex
            {
                get { return _currentPageIndex; }
            }

            public string PageURL
            {
                get { return _pageURL; }
            }

            public int Index
            {
                get { return _index; }
            }

            public string QueryStringPageName
            {
                get { return _queryStringPageName; }
            }


            public static string GetValidUrl(string pageUrl, string queryStringParamName, int pageIndex)
            {
                return string.Concat(pageUrl, pageUrl.Contains("?") ? "&" : "?", queryStringParamName, "=", pageIndex);
            }
        }
    }
}